home *** CD-ROM | disk | FTP | other *** search
- #ifndef _H_RTTI_MACROS
- #define _H_RTTI_MACROS
-
- /* %Z%%I% %G% %U% %W% */
- /*
- * COMPONENT_NAME: (COMINC) Common Header File for RTTI
- *
- * ORIGINS: 27
- *
- * (C) COPYRIGHT International Business Machines Corp. 1992
- * This work was supported by a grant from International Business
- * Machines, Inc. These procedures are contributed to the public domain
- * by International Business Machines Inc. "AS IS" without any warranty
- * of any kind including the warranty of merchantability or fitness
- * for a particular purpose.
- *
- *
- * This is free software. Feel free to redistribute and/or modify it.
- * Please send us e-mail and let us know if you have any problems
- * or suggestions.
- *
- * Arindam Banerji
- * axb@cse.nd.edu
- *
- */
-
-
- // rttimacros.h
- // This file contains the macro definitions for automatically generating
- // the appropriate declarations (to be found within class declarations
- // or .h files) and the function/data definitions (to be found in class
- // definition files or .c files). There are different sets of macros
- // for generating these declarations and definitions for both non-template
- // and template classes. In most cases, the macros defined here are not
- // meant for human consumption. Either look at sample code or at a
- // document that explains the usage of these macros. A word of
- // warning is in order about the template macros - they have only been
- // been tested with cfront and xlC. Since, templates are notoriously
- // non-portable - these macros are not guaranteed to work with all
- // compilers.
-
- /*****************
- RTTI DECLARATION AND IMPLEMENTATION MACROS.
- ****************/
-
- // macro definition to aid in the declaration of RTTI scaffolding
- // Use RTTI_SCAFFOLDING_DECL for non_template classes as in
- // class foo : public virtual CLASS. Use this macro in the .h file, within
- // the class declaration.
- #define RTTI_SCAFFOLDING_DECL(TYPE) \
- static const Type_info info_obj ; \
- virtual typeid get_info() const ; \
- virtual void *get_this_ptr(void) const ; \
- static typeid info() ; \
- static TYPE *_narrow(CLASS *) ; \
-
- // Use RTTI_SCAFFOLDING_DECL_TEMPL for template classes with just one
- // parameter. Again use this within the .h file.
- #define RTTI_SCAFFOLDING_DECL_TEMPL(TYPE) \
- static const Type_info info_obj ; \
- virtual typeid get_info() const ; \
- virtual void *get_this_ptr(void) const ; \
- static typeid info() ; \
- static TYPE *_narrow(CLASS *) ; \
- static const Type_info *base_set[] ; \
-
- // Use RTTI_SCAFFOLDING_DECL_TEMPL_2 for template classes with two
- // parameters. Again use this within the .h file ie: for
- // template <class T, int n> class foo1 { .....
- // use RTTI_SCAFFOLDING_DECL_TEMPL_2(foo1,T,n)
- #define RTTI_SCAFFOLDING_DECL_TEMPL_2(NAME,I1,I2) \
- static const Type_info info_obj ; \
- virtual typeid get_info() const ; \
- virtual void *get_this_ptr(void) const ; \
- static typeid info() ; \
- static NAME<I1,I2> *_narrow(CLASS *) ; \
- static const Type_info *base_set[] ; \
-
- // Use RTTI_SCAFFOLDING_DECL_TEMPL_3 for template classes with three
- // parameters. Again use this within the .h file ie: for
- // template <class T, int n, class Z> class foo1 { .....
- // use RTTI_SCAFFOLDING_DECL_TEMPL_3(foo1,T,n,Z)
- #define RTTI_SCAFFOLDING_DECL_TEMPL_3(NAME,I1,I2,I3) \
- static const Type_info info_obj ; \
- virtual typeid get_info() const ; \
- virtual void *get_this_ptr(void) const ; \
- static typeid info() ; \
- static NAME<I1,I2,I3> *_narrow(CLASS *) ; \
- static const Type_info *base_set[] ; \
-
-
-
- // An useful set of macros to get the name of a particular class. The
- // ones without any parameters are used to get the name of a class from
- // within the class member functions. The other two are used to get the
- // name of any arbitrary class, given a pointer to an object of the class.
- // The macros in CAPITALS get the static class name ie: the immediate
- // name of the object, whereas the macros in non-capital letters get the
- // dynamic name of the class. Be careful and make sure that these are
- // use only when classes being referred to are complete (ie: not during
- // initialization).
- #define __CLASSNAME (GET_PTR_INFO(this))->name()
- #define __classname (GET_PTR_INFO(get_this_ptr()))->name()
- #define _CLASSNAME(p) (GET_PTR_INFO(p))->name()
- #define _classname(p) (GET_PTR_INFO(p->get_this_ptr()))->name()
-
- // The following declarations aid in implementing the RTTI scafoolding on a
- // per class basis. The IMPL0, IMPL1 etc variations are geared to deal with
- // classes with varying sets of parents. Call these macros with only the
- // names of the direct base classes. They are meant for non-template
- // classes. In most cases, users should not have to use these macros at all.
- #define NON_TEMPL_NARROW(TYPE) \
- TYPE *TYPE::_narrow(CLASS *obj) \
- { \
- void *ret = NULL ; \
- if ( ptr_cast(TYPE,obj)) \
- ret = obj->get_this_ptr() ; \
- return ( (TYPE *) ret) ; \
- } \
-
- #define GET_THIS_PTR(TYPE) \
- void *TYPE::get_this_ptr(void) const \
- { \
- return ((void *) this); \
- } \
-
- // The following macro is used within other macros to form a part of the
- // RTTI scaffolding that goes into .c files. This again is used with non-
- // template classes.
- #define NARROWING_MECHANISM(TYPE) \
- NON_TEMPL_NARROW(TYPE) \
- GET_THIS_PTR(TYPE)
-
- // The following macros allow users to create the RTTI scaffoldings that
- // are a part of the class definitions (ie: they go in .c files).
-
- // RTTI_SACFFOLDING_IMPL0 is used to prepare the definition scaffolding
- // for non-template classes with no parent classes.
- #define RTTI_SCAFFOLDING_IMPL0(TYPE) \
- const Type_info TYPE::info_obj(#TYPE, 0) ;\
- typeid TYPE::get_info() const { return &info_obj; } \
- typeid TYPE::info() { return &info_obj; } \
- NARROWING_MECHANISM(TYPE) \
-
- // RTTI_SACFFOLDING_IMPL1 is used to prepare the definition scaffolding
- // for non-template classes with one parent classes ie : for
- // class foo : public virtual CLASS { ...
- // use RTTI_SCAFFOLDING_IMPL1(foo,CLASS)
- #define RTTI_SCAFFOLDING_IMPL1(TYPE, PARENT1) \
- static const Type_info* TYPE##_set_bases[] = \
- {(const Type_info *) &PARENT1::info_obj, 0 } ; \
- const Type_info TYPE::info_obj(#TYPE, TYPE##_set_bases) ;\
- typeid TYPE::get_info() const { return &info_obj; } \
- typeid TYPE::info() { return &info_obj; } \
- NARROWING_MECHANISM(TYPE) \
-
- // RTTI_SACFFOLDING_IMPL2 is used to prepare the definition scaffolding
- // for non-template classes with two parent classes ie : for
- // class foo : PARENT1, PARENT2 { ...
- // use RTTI_SCAFFOLDING_IMPL2(foo,PARENT1,PARENT2)
-
- #define RTTI_SCAFFOLDING_IMPL2(TYPE, PARENT1, PARENT2) \
- static const Type_info* TYPE##_set_bases[] = \
- { (const Type_info *) &PARENT1::info_obj, \
- (const Type_info *) &PARENT2::info_obj, 0 } ; \
- const Type_info TYPE::info_obj(#TYPE, TYPE##_set_bases) ;\
- typeid TYPE::get_info() const { return &info_obj; } \
- typeid TYPE::info() { return &info_obj; } \
- NARROWING_MECHANISM(TYPE) \
-
-
- // RTTI_SACFFOLDING_IMPL3 is used to prepare the definition scaffolding
- // for non-template classes with three parent classes ie : for
- // class foo : PARENT1, PARENT2, PARENT3 { ...
- // use RTTI_SCAFFOLDING_IMPL3(foo,PARENT1,PARENT2,PARENT3)
-
- #define RTTI_SCAFFOLDING_IMPL3(TYPE, PARENT1, PARENT2, PARENT3) \
- static const Type_info* TYPE##_set_bases[] = \
- { (const Type_info *) &PARENT1::info_obj, \
- (const Type_info *) &PARENT2::info_obj, \
- (const Type_info *) &PARENT3::info_obj,0} ; \
- const Type_info TYPE::info_obj(#TYPE, TYPE##_set_bases) ;\
- typeid TYPE::get_info() const { return &info_obj; } \
- typeid TYPE::info() { return &info_obj; } \
- NARROWING_MECHANISM(TYPE) \
-
-
- // RTTI_SACFFOLDING_IMPL4 is used to prepare the definition scaffolding
- // for non-template classes with 4 parent classes ie : for
- // class foo : PARENT1, PARENT2, PARENT3, PARENT4 { ...
- // use RTTI_SCAFFOLDING_IMPL4(foo,PARENT1,PARENT2,PARENT3,PARENT4)
-
- #define RTTI_SCAFFOLDING_IMPL4(TYPE,PARENT1,PARENT2,PARENT3,PARENT4) \
- static const Type_info* TYPE##_set_bases[] = \
- { (const Type_info *) &PARENT1::info_obj, \
- (const Type_info *) &PARENT2::info_obj, \
- (const Type_info *) &PARENT3::info_obj, \
- (const Type_info *) &PARENT4::info_obj, 0}; \
- const Type_info TYPE::info_obj(#TYPE, TYPE##_set_bases) ;\
- typeid TYPE::get_info() const { return &info_obj; } \
- typeid TYPE::info() { return &info_obj; } \
- NARROWING_MECHANISM(TYPE) \
-
- /*********************************
- TEMPLATE STRING MANIPULATION MACROS - Not necessarily decipherable
- **********************************/
-
- #define tempstr(a) # a
- #define xtempstr(a) a
- #define rest_of_initial(y) y ## "<"
- #define rest_of_final(y) y ## ">"
-
- #define make_initial(x) rest_of_initial(# x)
- #define do_str(a,b) a ## b
- #define make_str(a,b) do_str(a,b)
-
- #define make_first_part(a,b) make_str(make_initial(a),#b)
- #define make_first_part1(a) rest_of_initial(tempstr(a))
- #define make_first_half(m,n) make_str(make_first_part(m,n), ",")
- #define make_final(x) rest_of_final( # x)
- #define add_comma(x) make_str(tempstr(x), ",")
-
- #define join_first_part(a,b,c) \
- make_str(make_first_half(a,b), add_comma(c))
-
- #define MAKE2_TEMPL_PARTS(a,b,c) make_str(make_first_half(a,b),make_final(c))
- #define MAKE1_TEMPL_PARTS(a,b) make_str(make_first_part1(a),make_final(b))
- #define MAKE3_TEMPL_PARTS(a,b,c,d) \
- make_str(join_first_part(a,b,c), make_final(d))
-
-
-
- /*********************************
- TEMPLATE MACROS BEGIN HERE
- **********************************/
-
-
- /*****************************
- FOLLOWING FEW MACROS ARE NOT FOR HUMAN CONSUMPTION
- *****************************/
-
- #define TEMPL_NARROWING1(TYPE,PARM1) \
- template <PARM1> TYPE *TYPE::_narrow(CLASS *obj) \
- { \
- void *ret = NULL ; \
- if ( ptr_cast(TYPE,obj)) \
- ret = obj->get_this_ptr() ; \
- return ( (TYPE *) ret) ; \
- } \
- template <PARM1> void *TYPE::get_this_ptr(void) const \
- { \
- return ((void *) this); \
- } \
-
- #define TEMPL_NARROWING2(NAME,PARM1,PARM2,I1,I2) \
- template <PARM1,PARM2> \
- NAME<I1,I2> *NAME<I1,I2>::_narrow(CLASS *obj) \
- { \
- void *ret = NULL ; \
- if ( ptr_cast_2(NAME,I1,I2,obj)) \
- ret = obj->get_this_ptr() ; \
- return ( (NAME<I1,I2> *) ret) ; \
- } \
- template <PARM1,PARM2> \
- void *NAME<I1,I2>::get_this_ptr(void) const \
- { \
- return ((void *) this); \
- } \
-
- #define TEMPL_NARROWING3(NAME,PARM1,PARM2,PARM3,I1,I2,I3) \
- template <PARM1,PARM2,PARM3> \
- NAME<I1,I2,I3> *NAME<I1,I2,I3>::_narrow(CLASS *obj) \
- { \
- void *ret = NULL ; \
- if ( ptr_cast_3(NAME,I1,I2,I3,obj)) \
- ret = obj->get_this_ptr() ; \
- return ( (NAME<I1,I2,I3> *) ret) ; \
- } \
- template <PARM1,PARM2,PARM3> \
- void *NAME<I1,I2,I3>::get_this_ptr(void) const \
- { \
- return ((void *) this); \
- } \
-
-
- #define TEMPL_RTTI_IMPL_1(TYPE,PARM1) \
- template < PARM1 > typeid TYPE::get_info() const { return &info_obj; } \
- template < PARM1 > typeid TYPE::info() { return &info_obj; } \
- TEMPL_NARROWING1(TYPE,PARM1)
-
- #define TEMPL_RTTI_IMPL_2(NAME,PARM1,PARM2,I1,I2) \
- template <PARM1,PARM2> \
- typeid NAME<I1,I2>::get_info() const { return &info_obj; } \
- template <PARM1,PARM2> \
- typeid NAME<I1,I2>::info() { return &info_obj; } \
- TEMPL_NARROWING2(NAME,PARM1,PARM2,I1,I2)
-
- #define TEMPL_RTTI_IMPL_3(NAME,PARM1,PARM2,PARM3,I1,I2,I3) \
- template <PARM1,PARM2,PARM3> \
- typeid NAME<I1,I2,I3>::get_info() const { return &info_obj; } \
- template <PARM1,PARM2,PARM3> \
- typeid NAME<I1,I2,I3>::info() { return &info_obj; } \
- TEMPL_NARROWING3(NAME,PARM1,PARM2,PARM3,I1,I2,I3)
-
-
- /*****************************
- FOLLOWING MACROS ARE USED TO SPECIFY IMPLEMENTATION SCAFFOLDINGS FOR
- TEMPLATE CLASSES
- *****************************/
-
- // The following macro are used for template classes that have no base
- // classes and have 1 arguments ie : for
- // template <class T> class foo { ...
- // use TEMPL_RTTI_IMPL_SCAFF_0_1(foo<T>,foo,class T)
- #define TEMPL_RTTI_IMPL_SCAFF_0_1(TYPE,NAME,PARM1) \
- template <PARM1> \
- const Type_info TYPE::info_obj(MAKE1_TEMPL_PARTS(NAME,PARM1), 0); \
- TEMPL_RTTI_IMPL_1(TYPE,PARM1)
-
- // The following macro are used for template classes that have no base
- // classes and have 2 arguments ie : for
- // template <class T, int n > class foo { ...
- // use TEMPL_RTTI_IMPL_SCAFF_0_2(foo,class T, int n , T, n)
- #define TEMPL_RTTI_IMPL_SCAFF_0_2(NAME,PARM1,PARM2,I1,I2) \
- template <PARM1,PARM2> const Type_info \
- NAME<I1,I2>::info_obj(MAKE2_TEMPL_PARTS(NAME,PARM1,PARM2), 0) ; \
- TEMPL_RTTI_IMPL_2(NAME,PARM1,PARM2,I1,I2)
-
- // The following macro are used for template classes that have no base
- // classes and have 3 arguments ie : for
- // template <class T, int n, class Z > class foo { ...
- // use TEMPL_RTTI_IMPL_SCAFF_0_3(foo,class T, int n ,class Z, T, n,Z)
- #define TEMPL_RTTI_IMPL_SCAFF_0_3(NAME,PARM1,PARM2,PARM3,I1,I2,I3) \
- template <PARM1,PARM2,PARM3> const Type_info \
- NAME<I1,I2,I3>::info_obj(MAKE3_TEMPL_PARTS(NAME,PARM1,PARM2,PARM3), 0) ; \
- TEMPL_RTTI_IMPL_3(NAME,PARM1,PARM2,PARM3,I1,I2,I3)
-
-
- // The following macro are used for template classes that have 1 base
- // classes and have 1 arguments ie : for
- // template <class T > class foo : public foop<T> { ...
- // use TEMPL_RTTI_IMPL_SCAFF_1_1(foo<T>,foo, class T, foop<T>)
- #define TEMPL_RTTI_IMPL_SCAFF_1_1(TYPE,NAME,PARM1,PARENT) \
- template <PARM1> \
- const Type_info *TYPE::base_set[2] = \
- { (const Type_info *) &PARENT::info_obj, 0 } ; \
- template <PARM1> \
- const Type_info TYPE::info_obj(MAKE1_TEMPL_PARTS(NAME,PARM1), \
- TYPE::base_set) ; \
- TEMPL_RTTI_IMPL_1(TYPE,PARM1)
-
- // The following macro are used for template classes that have 1 base
- // classes and have 2 arguments ie : for
- // template <class T,int n > class foo : public foop<T> { ...
- // use TEMPL_RTTI_IMPL_SCAFF_1_2(foo,class T,int n,foop<T>,T,n)
- #define TEMPL_RTTI_IMPL_SCAFF_1_2(NAME,PARM1,PARM2,PARENT,I1,I2) \
- template <PARM1,PARM2> \
- const Type_info *NAME<I1,I2>::base_set[2] = \
- { (const Type_info *) &PARENT::info_obj, 0 } ; \
- template <PARM1,PARM2> const Type_info \
- NAME<I1,I2>::info_obj(MAKE2_TEMPL_PARTS(NAME,PARM1,PARM2), \
- NAME<I1,I2>::base_set) ; \
- TEMPL_RTTI_IMPL_2(NAME,PARM1,PARM2,I1,I2)
-
-
- // The following macro are used for template classes that have 1 base
- // classes and have 3 arguments ie : for
- // template <class T,int n,class Z > class foo : public foop<T> { ...
- // use TEMPL_RTTI_IMPL_SCAFF_1_3(foo,class T,int n,class Z,foop<T>,T,n,Z)
- #define TEMPL_RTTI_IMPL_SCAFF_1_3(NAME,PARM1,PARM2,PARM3,PARENT,I1,I2,I3) \
- template <PARM1,PARM2,PARM3> \
- const Type_info *NAME<I1,I2,I3>::base_set[2] = \
- { (const Type_info *) &PARENT::info_obj, 0 } ; \
- template <PARM1,PARM2,PARM3> const Type_info \
- NAME<I1,I2,I3>::info_obj(MAKE3_TEMPL_PARTS(NAME,PARM1,PARM2,PARM3), \
- NAME<I1,I2,I3>::base_set) ; \
- TEMPL_RTTI_IMPL_3(NAME,PARM1,PARM2,PARM3,I1,I2,I3)
-
-
- // The following macro are used for template classes that have 2 base
- // classes and have 1 arguments ie : for
- // template <class T > class foo : foop1<T>, foop2<T> { ...
- // use TEMPL_RTTI_IMPL_SCAFF_2_1(foo<T>,foo, class T, foop1<T>,foop2<T>)
- #define TEMPL_RTTI_IMPL_SCAFF_2_1(TYPE,NAME,PARM1,P1,P2) \
- template <PARM1> \
- const Type_info *TYPE::base_set[3] = \
- { (const Type_info *) &P1::info_obj, \
- (const Type_info *) &P2::info_obj, 0 } ; \
- template <PARM1> \
- const Type_info TYPE::info_obj(MAKE1_TEMPL_PARTS(NAME,PARM1), \
- TYPE::base_set) ; \
- TEMPL_RTTI_IMPL_1(TYPE,PARM1)
-
-
- // The following macro are used for template classes that have 2 base
- // classes and have 2 arguments ie: for
- // template <class T,int n > class foo : foop1<T>,foop2<T> { ...
- // use TEMPL_RTTI_IMPL_SCAFF_2_2(foo,class T,int n,foop1<T>,foop2<T>,T,n)
- #define TEMPL_RTTI_IMPL_SCAFF_2_2(NAME,PARM1,PARM2,P1,P2,I1,I2) \
- template <PARM1,PARM2> \
- const Type_info *NAME<I1,I2>::base_set[3] = \
- { (const Type_info *) &P1::info_obj, \
- (const Type_info *) &P2::info_obj, 0 } ; \
- template <PARM1,PARM2> const Type_info\
- NAME<I1,I2>::info_obj(MAKE2_TEMPL_PARTS(NAME,PARM1,PARM2), \
- NAME<I1,I2>::base_set) ; \
- TEMPL_RTTI_IMPL_2(NAME,PARM1,PARM2,I1,I2)
-
- // The following macro are used for template classes that have 2 base
- // classes and have 3 arguments ie: for
- // template <class T,int n,class Z > class foo : foop1<T>,foop2<T> { ...
- // use TEMPL_RTTI_IMPL_SCAFF_2_3(foo,class T,int n,class Z,foop1<T>,foop2<T>,T,n,Z)
- #define TEMPL_RTTI_IMPL_SCAFF_2_3(NAME,PRM1,PRM2,PRM3,P1,P2,I1,I2,I3) \
- template <PRM1,PRM2,PRM3> \
- const Type_info *NAME<I1,I2,I3>::base_set[3] = \
- { (const Type_info *) &P1::info_obj, \
- (const Type_info *) &P2::info_obj, 0 } ; \
- template <PRM1,PRM2,PRM3> const Type_info \
- NAME<I1,I2,I3>::info_obj(MAKE3_TEMPL_PARTS(NAME,PRM1,PRM2,PRM3), \
- NAME<I1,I2,I3>::base_set) ; \
- TEMPL_RTTI_IMPL_3(NAME,PRM1,PRM2,PRM3,I1,I2,I3)
-
-
- // The following macro are used for template classes that have 3 base
- // classes and have 1 arguments ie: for
- // template <class T > class foo : foop1<T>, foop2<T>,foop3<T> { ...
- // use TEMPL_RTTI_IMPL_SCAFF_3_1(foo<T>,foo, class T,foop1<T>,foop2<T>,foop3<T>)
- #define TEMPL_RTTI_IMPL_SCAFF_3_1(TYPE,NAME,PARM1,P1,P2,P3) \
- template <PARM1> \
- const Type_info *TYPE::base_set[4] = \
- { (const Type_info *) &P1::info_obj, \
- (const Type_info *) &P2::info_obj, \
- (const Type_info *) &P3::info_obj, 0 } ; \
- template <PARM1> \
- const Type_info TYPE::info_obj(MAKE1_TEMPL_PARTS(NAME,PARM1), \
- TYPE::base_set) ; \
- TEMPL_RTTI_IMPL_1(TYPE,PARM1)
-
- // The following macro are used for template classes that have 3 base
- // classes and have 2 arguments ie: for
- // template <class T,int n > class foo : foop1<T>,foop2<T>,foop3<T> { ...
- // use TEMPL_RTTI_IMPL_SCAFF_3_2(foo,class T,int n,foop1<T>,foop2<T>,foop3<T>,T,n)
-
- #define TEMPL_RTTI_IMPL_SCAFF_3_2(NAME,PARM1,PARM2,P1,P2,P3,I1,I2) \
- template <PARM1,PARM2> \
- const Type_info *NAME<I1,I2>::base_set[4] = \
- { (const Type_info *) &P1::info_obj, \
- (const Type_info *) &P2::info_obj, \
- (const Type_info *) &P3::info_obj, 0 } ; \
- template <PARM1,PARM2> const Type_info \
- NAME<I1,I2>::info_obj(MAKE2_TEMPL_PARTS(NAME,PARM1,PARM2), \
- NAME<I1,I2>::base_set) ; \
- TEMPL_RTTI_IMPL_2(NAME,PARM1,PARM2,I1,I2)
-
- // The following macro are used for template classes that have 3 base
- // classes and have 3 arguments ie: for
- // template <class T,int n,class Z> class foo : foop1<T>,foop2<T>,foop3<T> { ...
- // use TEMPL_RTTI_IMPL_SCAFF_3_3(foo,class T,int n,class Z,foop1<T>,foop2<T>,foop3<T>,T,n,Z)
-
- #define TEMPL_RTTI_IMPL_SCAFF_3_3(NAME,PRM1,PRM2,PRM3,P1,P2,P3,I1,I2,I3) \
- template <PRM1,PRM2,PRM3> \
- const Type_info *NAME<I1,I2,I3>::base_set[4] = \
- { (const Type_info *) &P1::info_obj, \
- (const Type_info *) &P2::info_obj, \
- (const Type_info *) &P3::info_obj, 0 } ; \
- template <PRM1,PRM2,PRM3> const Type_info\
- NAME<I1,I2,I3>::info_obj(MAKE3_TEMPL_PARTS(NAME,PRM1,PRM2,PRM3), \
- NAME<I1,I2,I3>::base_set) ; \
- TEMPL_RTTI_IMPL_3(NAME,PRM1,PRM2,PRM3,I1,I2,I3)
-
-
- #endif // _H_RTTI_MACROS
-